#include <iostream>
#include "map.h"
#include <conio.h>
#include <Windows.h>
#include <time.h>

#include <vector>
#include <stack>
#include <queue>

using namespace std;

Map::Map(int size){
	Grape_Size = size;
	for(int i = 0;i < Grape_Size;i ++){
		for(int j = 0;j < Grape_Size;j ++){
			Grape[i][j] = Wall; 
		}	
	}
	
	for(int n = 0;n < Grape_Size;n ++){
		for(int m = 0; m < Grape_Size;m ++){
			visited[n][m] = 0;
		}	
	}

	for (int j = 0; j < MAX + 2; j++)
		for (int m = 0; m < MAX + 2; ++m)
			buffer[j][m] = 0;
	idx = 0;
}

void Map::Creat(int size)
{
	//最外围设置为路，可以有效的保护里面一层墙体，并防止挖出界
	for (int i = 0; i < Grape_Size ; i++) 
	{
		Grape[i][0] = Road;
		Grape[0][i] = Road;
		Grape[Grape_Size - 1][i] = Road;
		Grape[i][Grape_Size - 1] = Road;
	}
	 
	//墙队列，包括X , Y
	vector<int> X;
	vector<int> Y;
	 
	//任取初始值
	X.push_back(2);
	Y.push_back(2);

	srand((unsigned int)time(NULL));
	 
	//当墙队列为空时结束循环
	while (X.size()) 
	{
		//在墙队列中随机取一点
		int r = rand() % X.size();
		int x = X[r];
		int y = Y[r];
	 
		//判读上下左右四个方向是否为路
		int count = 0;
		for (int i = x - 1; i < x + 2; i++) 
		{ 
			for (int j = y - 1; j < y + 2; j++) 
			{
				if (abs(x - i) + abs(y - j) == 1 && Grape[i][j] == Road)
				{
					++count;
				}
			}
		}
	 
		if (count <= 1) {
			Grape[x][y] = Road;
			// 在墙队列中插入新的墙
			for (int i = x - 1; i < x + 2; i++) 
			{
				for (int j = y - 1; j < y + 2; j++) 
				{
					if (abs(x - i) + abs(y - j) == 1 && Grape[i][j] == Wall) 
					{
						X.push_back(i);
						Y.push_back(j);
					}
				}
			}
		}
	 
		//删除当前墙
		X.erase(X.begin() + r);
		Y.erase(Y.begin() + r);
	}

	//设置迷宫进出口
	Grape[Grape_Size / 2][Grape_Size / 2] = Mouse;
	for (int i = Grape_Size - 3; i >= 0; i--) {
		if (Grape[i][Grape_Size - 3] == Road) {
			Out_x = i;
			Out_y = Grape_Size - 2;
			Grape[i][Grape_Size - 2] = End;
			break;
		}
	}
}

void Map::Display(){
	// idx = (idx + 1) % 2;
	for(int i = 0;i < Grape_Size;i ++){
		for(int j = 0;j < Grape_Size;j ++){
			if(Grape[i][j] == Road){
				cout << " "; //buffer[i][j] = ' ';// cout << " "; //
			}
			else if(Grape[i][j] == Wall){
				cout << "#"; // buffer[i][j] = '#'; // cout << "#"; // 
			}
			else if(Grape[i][j] == End){
				cout << "C"; // buffer[i][j] = 'C'; // cout << "C"; // 
			}
			else if(Grape[i][j] == Visited){
				cout << "+"; // buffer[i][j] = '+'; // cout << "+"; // 
			}
			else if (Grape[i][j] == Mouse) {
				cout << "@"; // buffer[i][j] = '@'; // cout << "@"; //
			}
			else
			{
				cout << "$"; // buffer[i][j] = '$'; // cout << "$"; // 
			}
		}
		cout << "\n"; // buffer[i][Grape_Size] = '\n';
	}
}

void Map::Visite(){
	// ::std::system("cls");
	// Display();
	for(int i = 0;i < Grape_Size;i ++){
		for(int j = 0;j < Grape_Size;j ++){
			if (Grape[i][j] == Wall)
			{
				cout << "#";
			}
			else if (Grape[i][j] == Visited) {
				cout << "+";
			}
			else
			{
				cout << " ";
			}
		}
		cout << endl;
	}
}

bool Map::Move(){
	Clear();
	const int xx = 1000;
	int count = 60 * xx;
	int t = time(NULL);
	M_x = Grape_Size / 2;
	M_y = Grape_Size / 2;

	::std::system("cls");
	Display();

	HANDLE hOutput;
	COORD coord = { 0,0 };
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

	while(count >= 0){
		if(_kbhit() == 0)
		{
			if(count > 0){
				Sleep(200);
				coord.X = 0;
				coord.Y = 0;
				SetConsoleCursorPosition(hOutput, coord);
				cout << "剩余时间：" << count / xx << endl;

				count -= 200;

				if(count == 0){
					cout << "闯关失败";
					return false;
					//break; 
				}
			}
		}
		else{
			char get = getch();
			coord.X = M_y;
			coord.Y = M_x;
			switch(get){
				case 'a':
					Left();
					//Display();
					break;
				case 's':
					Down();
					//Display();
					break;
				case 'd':
					Right();
					//Display();
					break;
				case 'w':
					Up();
					//Display();
					break;
			}
			SetConsoleCursorPosition(hOutput, coord);
			cout << '+';
			coord.X = M_y;
			coord.Y = M_x;
			SetConsoleCursorPosition(hOutput, coord);
			cout << '@';
			// ::std::system("cls");

			// Display();
		}
		if(M_x == Out_x && M_y == Out_y){
			cout << "恭喜你闯关成功！" << endl;
			Grape[M_x][M_y] = Visited;
			return true;
		}
	}
	return false;
}

void Map::Up(bool change){
	if(M_y <= 0){
		return;
	}
	else if(!change && Grape[M_x - 1][M_y] != Wall){
		Grape[M_x][M_y] = Visited;
		M_x --;
		Grape[M_x][M_y] = Mouse;
	}
	else if (change)
	{
		if (Grape[M_x][M_y] > Mouse)
			Grape[M_x][M_y] -= (Mouse + 1);
		M_x--;
		Grape[M_x][M_y] = Mouse + Grape[M_x][M_y] + 1;
	}
}

void Map::Down(bool change){
	if(M_y > Grape_Size - 1){
		return;
	}
	else if(!change && Grape[M_x + 1][M_y] != Wall){
		Grape[M_x][M_y] = Visited;
		M_x ++;
		Grape[M_x][M_y] = Mouse;
	}
	else if (change)
	{
		if (Grape[M_x][M_y] > Mouse)
			Grape[M_x][M_y] -= (Mouse + 1);
		M_x++;
		Grape[M_x][M_y] = Mouse + Grape[M_x][M_y] + 1;
	}
}

void Map::Left(bool change){
	if(M_x <= 0){
		return;
	}
	else if(!change && Grape[M_x][M_y - 1] != Wall){
		Grape[M_x][M_y] = Visited;
		M_y--;
		Grape[M_x][M_y] = Mouse;
	}
	else if (change)
	{
		if (Grape[M_x][M_y] > Mouse)
			Grape[M_x][M_y] -= (Mouse + 1);
		M_y--;
		Grape[M_x][M_y] = Mouse + Grape[M_x][M_y] + 1;
	}
}

void Map::Right(bool change){
	if(M_x > Grape_Size - 1){
		return;
	}
	else if(!change && Grape[M_x][M_y + 1] != Wall){
		Grape[M_x][M_y] = Visited;
		M_y ++;
		Grape[M_x][M_y] = Mouse;
	}
	else if (change)
	{
		if (Grape[M_x][M_y] > Mouse)
			Grape[M_x][M_y] -= (Mouse + 1);
		M_y++;
		Grape[M_x][M_y] = Mouse + Grape[M_x][M_y] + 1;
	}
}

void Map::Change(){
	std::system("cls");
	Clear();
	char change = 0;
	// char change2 = _getch();
	bool changed = false;
	bool iskeep = false;
	M_x = Grape_Size / 2;
	M_y = Grape_Size / 2;
	Grape[M_x][M_y] = Mouse;
	Display();
	while(1){
		if (_kbhit() != 0) {
			change = getch();
			changed = false;
			switch (change) {
			case 'a':
				Left(true);
				break;
			case 's':
				Down(true);
				break;
			case 'd':
				Right(true);
				break;
			case 'w':
				Up(true);
				break;
			case 0x0D: //回车
				changed = true;
				break;
			case 27: // ESC 退出
				cout << "保存地图成功！" << endl;
				// Grape[Grape_Size - 2][Grape_Size - 3] = End;
				Grape[Grape_Size / 2][Grape_Size / 2] = Mouse;
				std::system("pause");
				std::system("cls");
				return;
			default:
				break;
			}

			if (changed)
			{
				if (Grape[M_x][M_y] == Mouse + Wall + 1) {
					Grape[M_x][M_y] = Road;
				}
				else if (Grape[M_x][M_y] == Mouse + Road + 1)
				{
					Grape[M_x][M_y] = Wall;
				}
			}

			::std::system("cls");
			Display();
		}

//		if(iskeep == true){
//			for(int i = 0;i < Grape_Size;i ++){
//				for(int j = 0;j < Grape_Size;j ++){
//					if(Map[i][j] == Visited){
//						Map[i][j] = Road;
//					}
//				}
//			}
//			break;
//		}
	}
}

struct Point
{
	int x;
	int y;
	Point* previous;
	int step;
};

Point dir[4] = {
	{ 0, 1, NULL, 0 },
	{ 1, 0, NULL, 0 },
	{ 0, -1, NULL, 0 },
	{ -1, 0, NULL, 0 },
};


void Map::ShowPath()
{
	queue<Point> Q;
	Q.push(Point{ Grape_Size / 2, Grape_Size / 2, NULL, 0 });
	Point cur = { };

	while (!Q.empty())
	{
		cur = Q.front();
		Q.pop();
		Grape[cur.x][cur.y] = Visited;

		//只有0位置可以走，到终点就是走出迷宫。
		// 向四面八方进行搜索，搜过过了就更改标记表示已经走过了。
		for (int i = 0; i < 4; ++i)
		{
			Point nxt{ cur.x + dir[i].x, cur.y + dir[i].y, NULL, 0 };
			if (nxt.x >= 0 && nxt.x < Grape_Size && nxt.y >= 0 && nxt.y < Grape_Size && 
				(Grape[nxt.x][nxt.y] == Road || Grape[nxt.x][nxt.y] == End))
			{
				Point* tmp = new Point;
				memcpy(tmp, &cur, sizeof(Point));
				nxt.previous = tmp;
				nxt.step = cur.step + 1;
				
				if (Grape[nxt.x][nxt.y] == End)
				{
					Map tmp = *this;

					tmp.Clear();

					Point* p = &nxt;
					while (p->previous != NULL)
					{
						tmp.Grape[p->x][p->y] = Visited;
						p = p->previous;
					}

					tmp.Visite();

					::std::cout << "------------------------------------\n\n";
					// ::std::system("pause");
					//这句话注释则输出所有路径，不注释是最短路径
					// return;
				}
				else
					Grape[nxt.x][nxt.y] = Visited;
				Q.push(nxt);
			}
		}
	}

	Clear();
	::std::system("pause");
}

void Map::Clear()
{
	for (int i = 0; i < Grape_Size; i++) {
		for (int j = 0; j < Grape_Size; j++) {
			if (Grape[i][j] == Visited)
				Grape[i][j] = Road;
		}
	}
	// Grape[Grape_Size - 2][Grape_Size - 3] = End;
	Grape[Grape_Size / 2][Grape_Size / 2] = Mouse;
}













































